# 基于随机算法的模版AI
# 此处采取的算法为优先在己方领域下, 己方满则在对方领域随机下

# 参赛队伍的AI要求:
#
# 须写在Player类里
#
# 须实现两个方法:
#
# __init__(self, isFirst, array):
#   -> 初始化
#   -> 参数: isFirst是否先手, 为bool变量, isFirst = True 表示先手
#   -> 参数: array随机序列, 为一个长度等于总回合数的list
#
# output(self, currentRound, board, mode):
#   -> 给出己方的决策(下棋的位置或合并的方向)
#   -> 参数: currentRound当前轮数, 为从0开始的int
#   -> 参数: board棋盘对象
#   -> 参数: mode模式, mode = 'position' 对应位置模式, mode = 'direction' 对应方向模式, 如果为 '_position' 和 '_direction' 表示在对应模式下己方无法给出合法输出
#   -> 返回: 位置模式返回tuple (row, column), row行, 从上到下为0到3的int; column列, 从左到右为0到7的int
#   -> 返回: 方向模式返回direction = 0, 1, 2, 3 对应 上, 下, 左, 右
#   -> 返回: 在己方无法给出合法输出时, 对返回值不作要求
#
# 其余的属性与方法请自行设计
import random
import math
import copy

class Stack:
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return self.items == []

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def peek(self):
        return self.items[len(self.items) - 1]

    def size(self):
        return len(self.items)



class Player:
    def __init__(self, isFirst, array):
        # 初始化
        self.isFirst = isFirst
        self.array = array
        self.board = None
        self.best_direction = None
        self.best_position = None
        # 后期优化可以考虑排一个direction和position决策的优先队列，防止best direction或position是None
        # 代码中暂时让best决策为None时选择随机一个方向
        self.depth = 3  # 待改，而且一到10就报错，还没弄明白怎么回事（，现在最大是9
        self.another = None  # 轮到己方下棋时，若下在己方棋盘则应该下的位置
        self.current_round = 0  # 表示当前进行的回合数
        # 现在还有一个问题是current_round需不需要复原。目前是没有写复原的。
        self.prev_stack = Stack()  # 用于回溯之前的棋盘，即用于cancel move

    def output(self, currentRound, board, mode):  # 由userinterface.py可得，主程序中调用output时传入的board参数为copy完毕的board对象
        self.board = board.copy()  # 注意：不能用deepcopy，会报错，chessboard类的copy方法已经是深拷贝
        self.current_round = currentRound

        if mode == 'position':  # 给出己方下棋的位置
            self.another = self.board.getNext(self.isFirst, currentRound)
            return self.choose_position()
        elif mode == 'direction':  # 给出己方合并的方向
            return self.choose_direction()
        else:  # mode参数为_position或者_direction
            return



    def choose_position(self):
        # 优先进攻，其次下在自己这里，其次下在对方那里（具体下在哪个位置？需要决策！）
        self.best_position = self.another
        if self.best_position != ():
            return self.best_position
        else:   # self.another可能为()（己方棋盘满了）
            available = self.board.getNone(not self.isFirst)  # 对方的允许落子点
            if not available:  # 整个棋盘已满
                return None
            else:
                from random import choice
                return choice(available)



    def contest(self):
        # 分为先后手 判断我方棋盘位置
        judgelist=[]
        if self.isFirst:
            for col in range(1,8):
                for row in range(0,4):
                    judgeyou=(row,col)
                    judgeme=(row,col-1)
                    # 按照从左往右第一个出现两方棋子交界处
                    if self.board.getValue(judgeyou)!=0 and (not self.board.getBelong(judgeyou)) and \
                       self.board.getValue(judgeme)!=0 and self.board.getBelong(judgeme):
                        # 前方没有危险， 不用撤回 也没法吃
                        if self.board.getValue(judgeyou)!=self.board.getValue(judgeme):
                            pass
                        # 前方有危险
                        elif self.board.getValue(judgeyou)==self.board.getValue(judgeme):
                            if row != 0:  # 上方有可存放棋子格子
                                judgeyouup=(row-1,col)
                                if self.board.getValue(judgeyouup) != 0 and (not self.board.getBelong(judgeyouup)):  # 得到上方路径上第一棋子 如果一直没有棋子 则也无必要
                                    judgelist.append(self.board.getValue(judgeyouup))
                            if row != 3:  # 下方有可以存放棋子格子
                                judgeyoudown=(row+1,col)
                                if self.board.getValue(judgeyoudown) != 0 and (not self.board.getBelong(judgeyoudown)):
                                    judgelist.append(self.board.getValue(judgeyoudown))
                            if col != 7:  # 右方有可以存放棋子路径
                                judgeyouright = (row, col + 1)
                                if self.board.getValue(judgeyouright) != 0 and (not self.board.getBelong(judgeyouright)):
                                    judgelist.append(self.board.getValue(judgeyouright))

                            self.best_direction = 3
                            for value in judgelist:
                                if value == self.board.getValue(judgeme)+1:  # judgelist中只要有一个value满足这个条件就得往左撤退
                                    self.best_direction = 2
                                else:
                                    continue
                            # 若没有value满足这个条件，则可以往右吃

        else:
            for col in range(6,-1,-1):  # 从6到0
                for row in range(0,4):
                    judgeyou=(row,col)
                    judgeme=(row,col+1)
                    # 按照从左往右第一个出现两方棋子交界处
                    if self.board.getValue(judgeyou)!=0 and self.board.getBelong(judgeyou) and \
                       self.board.getValue(judgeme)!=0 and (not self.board.getBelong(judgeme)):  # 这里我改了，注意这是我方后手，judgeme的应该是False才行
                        # 前方没有危险
                        if self.board.getValue(judgeyou) != self.board.getValue(judgeme):
                            pass
                        # 前方有危险
                        elif self.board.getValue(judgeyou)==self.board.getValue(judgeme):
                            if row != 0:  # 上方有可存放棋子格子
                                judgeyouup=(row-1,col)
                                if self.board.getValue(judgeyouup) != 0 and self.board.getBelong(judgeyouup):  # 得到上方路径上第一棋子 如果一直没有棋子 则也无必要
                                    judgelist.append(self.board.getValue(judgeyouup))
                            if row != 3:  # 下方有可以存放棋子格子
                                judgeyoudown=(row+1,col)
                                if self.board.getValue(judgeyoudown) != 0 and self.board.getBelong(judgeyoudown):
                                    judgelist.append(self.board.getValue(judgeyoudown))
                            if col != 0:  # 左方有可以存放棋子路径
                                judgeyouleft=(row,col-1)
                                if self.board.getValue(judgeyouleft) != 0 and self.board.getBelong(judgeyouleft):
                                    judgelist.append(self.board.getValue(judgeyouleft))

                            self.best_direction = 2
                            for value in judgelist:
                                if value == self.board.getValue(judgeme)+1:  # judgelist中只要有一个value满足这个条件就得往右撤退
                                    self.best_direction = 3
                                else:
                                    continue
                            # 若没有value满足这个条件，则可以往左吃

    def athena(self):
        # 先手棋局
        if self.isFirst and self.best_direction == 3:
            mylist = [None]*4  # 我方边界处棋子级别列表
            yourlist = [None]*4  # 对方边界（未必接壤）处棋子级别列表
            current_board = self.board.copy()
            self.board.move(self.isFirst, self.best_direction)
            for row in range(0,4):
                finished = False
                for col in range(7, -1, -1):
                    if self.board.getValue((row,col)) != 0 and self.board.getBelong((row,col)) and (not finished):
                        mylist[row] = self.board.getValue((row,col))
                        finished = True
            for row in range(0,4):
                finished = False
                for col in range(0,8):
                    if self.board.getValue((row,col)) != 0 and (not self.board.getBelong((row,col))) and (not finished):
                        yourlist[row] = self.board.getValue((row,col))
                        finished = True

            self.board = current_board  # 棋盘恢复
            current_board = self.board.copy()
            for i in range(0, 4):
                if mylist[i] == yourlist[i] and (mylist[i] is not None):
                    if self.board.move(self.isFirst, 2):
                        self.best_direction = 2  # 如果向左合法
                        self.board = current_board  # 棋盘恢复
                        return
                    self.board = current_board  # 棋盘恢复
                    current_board = self.board.copy()
                    if self.board.move(self.isFirst, 1):
                        self.best_direction = 1  # 优先级暂时按照从上到下   先看一下情况考虑是否要递归调用
                        self.board = current_board  # 棋盘恢复
                        return
                    self.board = current_board  # 棋盘恢复
                    current_board = self.board.copy()
                    if self.board.move(self.isFirst, 0):
                        self.best_direction = 0
                        self.board = current_board  # 棋盘恢复
                        return
                    self.board = current_board
                    return

        # 后手棋局

        if (not self.isFirst) and self.best_direction == 2:
            mylist = [None]*4  # 我方边界处棋子级别列表
            yourlist = [None]*4  # 对方边界（未必接壤）处棋子级别列表
            current_board = self.board.copy()
            self.board.move(self.isFirst, self.best_direction)
            for row in range(0, 4):
                finished = False
                for col in range(7, -1, -1):
                    if self.board.getValue((row, col)) != 0 and self.board.getBelong((row, col)) and (not finished):
                        yourlist[row] = self.board.getValue((row, col))
                        finished = True
            for row in range(0, 4):
                finished = False
                for col in range(0, 8):
                    if self.board.getValue((row, col)) != 0 and (not self.board.getBelong((row, col))) and (
                    not finished):
                        mylist[row] = self.board.getValue((row, col))
                        finished = True

            self.board = current_board
            current_board = self.board.copy()
            for i in range(0, 4):
                if mylist[i] == yourlist[i] and (mylist[i] is not None):
                    if self.board.move(self.isFirst, 3):
                        self.best_direction = 3  # 只能向右? 因为无法保证向上之后 会不会再次出现之前错位而一致的情况 但是也可以考虑决策出一个最好方向之后递归这个函数 看看可不可以
                        self.board = current_board  # 棋盘恢复
                        return
                    self.board = current_board
                    current_board = self.board.copy()
                    if self.board.move(self.isFirst, 1):
                        self.best_direction = 1  # 优先级暂时按照从上到下   先看一下情况考虑是否要递归调用
                        self.board = current_board  # 棋盘恢复
                        return
                    self.board = current_board
                    current_board = self.board.copy()
                    if self.board.move(self.isFirst, 0):
                        self.best_direction = 0
                        self.board = current_board  # 棋盘恢复
                        return
                    self.board = current_board
                    return




    def choose_direction(self):
        self.best_direction = None
        self.get_ChoiceValue(self.depth, -1000000000, 1000000000, -1, self.isFirst, 'direction')
        if self.best_direction is not None:
            return self.best_direction
        from random import shuffle
        directionList = [0, 1, 2, 3]
        shuffle(directionList)
        for direction in directionList:
            # board.move()返回棋盘是否变化，若为False则是非法行为。
            if self.board.move(self.isFirst, direction):
                return direction



    def get_BoardValue(self,player):  # player=-1时为己方，player=1时为对方
        isFirst = self.isFirst if player == -1 else (not self.isFirst)
        selfvalue = self.estimateValue(isFirst)  # 原先是-(self.estimateValue(isFirst))*player
        enemyvalue = self.estimateValue(not isFirst)
        return selfvalue - enemyvalue




    def get_ChoiceValue(self,depth,alpha,beta,player,isFirst,mode):   # isFirst表示当前player是否为先手(bool)
        # 运用negamax算法获取这一步决策的value值

        if depth == 0:
            return self.get_BoardValue(player)

        if self.current_round >= len(self.array) - 3:  # 迭代到的回合数快超过总回合数，剪掉搜索枝
            return self.get_BoardValue(player)

        if mode == 'direction':
            # 以下是防守形式，若向左向右走的value一样则优先选择往己方的后方合并。
            if isFirst:
                directionList = [0, 1, 3, 2]
            else:
                directionList = [0, 1, 2, 3]

            for direction in directionList:
                current_board = self.board.copy()
                if self.board.move(isFirst, direction):  # 此合并方向合法时make move
                    self.prev_stack.push(current_board)

                    if isFirst:  # 本层player为先手方，即下一步是另一方选择方向进行合并
                        value = -self.get_ChoiceValue(depth-1, -beta, -alpha, -player, not isFirst,'direction')
                    else:  # 本层player为后手方，即下一步是另一方选择位置下棋
                        self.current_round += 1  # 下一步就是下一回合了，所以要更新
                        value = -self.get_ChoiceValue(depth-1, -beta, -alpha, -player, not isFirst,'position')

                    self.board = self.prev_stack.pop()  # cancel move

                    if value >= beta:
                        if depth == self.depth:
                            self.best_direction = direction
                        return beta
                    if value > alpha:
                        if depth == self.depth:
                            self.best_direction = direction
                        alpha = value
                else:
                    self.board = current_board
                    continue
            return alpha


        else:  # mode == 'position'
            another = self.board.getNext(isFirst, self.current_round)
            if another != ():
                self.board.add(isFirst,another)
            else:
                available = self.board.getNone(not isFirst)
                if available:
                    from random import choice
                    self.board.add(isFirst, choice(available))
            isFirst = not isFirst  # 交换下棋方
            another = self.board.getNext(isFirst, self.current_round)
            if another != ():
                self.board.add(isFirst,another)
            else:
                available = self.board.getNone(not isFirst)
                if available:
                    from random import choice
                    self.board.add(isFirst, choice(available))
            isFirst = not isFirst

            if isFirst:
                directionList = [0, 1, 3, 2]
            else:
                directionList = [0, 1, 2, 3]

            for direction in directionList:
                current_board = self.board.copy()
                if self.board.move(isFirst, direction):  # 此合并方向合法时make move
                    self.prev_stack.push(current_board)

                    if isFirst:  # 本层player为先手方，即下一步是另一方选择方向进行合并
                        value = -self.get_ChoiceValue(depth-1, -beta, -alpha, -player, not isFirst,'direction')
                    else:  # 本层player为后手方，即下一步是另一方选择位置下棋
                        self.current_round += 1  # 下一步就是下一回合了，所以要更新
                        value = -self.get_ChoiceValue(depth-1, -beta, -alpha, -player, not isFirst,'position')

                    self.board = self.prev_stack.pop()  # cancel move

                    if value >= beta:
                        if depth == self.depth:
                            self.best_direction = direction
                        return beta
                    if value > alpha:
                        if depth == self.depth:
                            self.best_direction = direction
                        alpha = value
                else:
                    self.board = current_board
                    continue
            return alpha





    # 评估函数为estimaValue(self, isFirst)（chessboard类中已有getValue方法了，所以换了个名字）
    # 此函数为客观评价函数，即输入参数 阵营(isFirst) ，输出该阵营在此棋面下的value，不附带有主观性，敌我均可用
    # 将isFirst代表的阵营称为对象方，另一方则称为对方（这也深刻体现了该函数的客观性）
    # isFirst为bool值，isFirst = True相当于isFirst = 1，isFirst = False相当于isFirst = -1

    def estimateValue(self, isFirst):  #计算先手或后手方的棋面value
        smoothnessWeight = 0  ####平滑性权重0.12
        monotonicityWeight = 0.23  ####单调性权重0.23
        emptyCellsWeight = 0.21  ####空格数权重  0.21
        # islandsWeight = 0    ####孤岛数权重
        figureWeight = 0.42  ####棋子级别权重
        invadeWeight = 0  ####入侵对方时的权重0.18
        value = monotonicityWeight * self.monotonicityValue(isFirst) + \
                emptyCellsWeight * self.emptyCellsValue(isFirst) + \
                figureWeight * self.figureValue(isFirst)
        return value


    def figureValue(self, isFirst):  #将对象方棋子的级别加权求和 得到 棋子级别大小和数量提供的value
        selfside = isFirst
        selfscore = self.board.getScore(selfside)
        figurevalue = 0
        for i in selfscore:
            if i >= 7:  # 级别太低也没有加的必要
                figurevalue += 3 ** i
            elif i >= 5:
                figurevalue += 2 ** i
            elif i >= 3:
                figurevalue += i*2
        return figurevalue


    def emptyCellsValue(self, isFirst):  #计算对象方空位数value
        import math
        selfSide = isFirst
        selfEmptyCellsNums = len(self.board.getNone(selfSide))  # 对象方空位数
        '''此处计算式可更改，但是应有:在空格数较少时，value对空格数的导数较大，
           空格数较大时，value对空格数的导数较小'''
        if selfEmptyCellsNums != 0:
            emptyCellsvalue = math.log(selfEmptyCellsNums, 2)  # 这里有定义域问题，如果selfEmptyCellsNums=0则会报错,故增加一种情况。
            return emptyCellsvalue
        return 0  # 是否输出0，待改


    def islandsValue(self, isFirst):  # 若一个空格 周围没有 其他空格 或者 级别为1的棋子 时，将其称为孤岛，提供负的value
        import math
        selfSide = isFirst
        selfEmptyCellsPosList = self.board.getNone(selfSide)  # 获得对象方所有空格位置的列表
        islandNums = 0  # 孤岛数计数
        directionList = [(-1, 0), (1, 0), (0, -1), (0, 1)]  # 计算空格的上下左右位置时的辅助列表
        for cell in selfEmptyCellsPosList:  # 考虑每一个对象方空格
            isIsland = True  # 用于判断空格是否为孤岛
            i = 0  # 计数君
            # 遍历此空格上下左右的格子
            while i <= 3 and isIsland:
                newrow = cell[0] + directionList[i][0]
                newcol = cell[1] + directionList[i][1]
                newpos = (newrow, newcol)

                if newrow < 0 or newrow > 3:
                    # 行数不在棋盘范围内
                    pass
                elif (newcol - (1 - isFirst)*4) < 0 or (newcol - (1 - isFirst)*4) > 3:
                    # 列数不在对象方棋盘范围内
                    pass
                elif self.board.getValue(newpos) <= 1:  # 若 空格旁的这个格子 级别小于等于1，则其必定是对象方的'2'或者空格
                    isIsland = False

                i += 1

            if isIsland:
                islandNums += 1
        '''此处可更改表达式，但应保证value为负值'''
        islandsvalue = - math.pow(islandNums, 1.2)
        return islandsvalue

    def smoothnessValue(self, isFirst): # 计算对象方棋子的平滑性，不平滑带来的value应为负值
        selfSide = isFirst
        smoothnessvalue = 0   # 初始化平滑性value
        directionList = [(-1, 0), (1, 0), (0, -1), (0, 1)]
        # 遍历棋盘上每一个格子（因为对象方棋子可能在对方棋盘内有分布）
        for row in range(0, 4):
            for col in range(0, 8):
                # 如果此格为对象方的棋子，则要考虑其与邻近的对象方棋子贡献的平滑性value
                if selfSide == self.board.getBelong((row, col)) and\
                      self.board.getValue((row, col)) != 0:
                    # level代表此格棋子的级别
                    level = self.board.getValue((row, col))
                    # 遍历此格棋子上下左右的格子
                    for i in range(4):
                        newrow = row + directionList[i][0]
                        newcol = col + directionList[i][1]
                        # 如果此方向的格子超界，则不用考虑此方向
                        if (newrow) < 0 or (newrow) > 3 or\
                                (newcol) < 0 or (newcol) > 7:
                            pass
                        # 如果此方向的格子上为对象方棋子，则要考虑平滑性影响
                        elif selfSide == self.board.getBelong((newrow, newcol)) and\
                            self.board.getValue((newrow, newcol)) != 0:
                            newLevel = self.board.getValue((newrow, newcol))
                            # deltaLevel代表两棋子的级别差
                            deltaLevel = abs(level - newLevel)
                            '''此处表达式可以修改，但应保证smoothnessvalue非正'''
                            smoothnessvalue -= deltaLevel ** 2

        return smoothnessvalue

    def invadeValue(self, isFirst):  # 建立敌后根据地
        selfSide = isFirst
        enemySide = not isFirst
        invadevalue = 0
        directionList = [(-1, 0), (1, 0), (0, -1), (0, 1)]
        # 对对方的棋盘遍历，
        for row in range(4):
            for col in range(isFirst*4, 4+isFirst*4):

                # 找出对方棋盘中的对象方棋子
                if selfSide == self.board.getBelong((row, col)):

                    # level 为该棋子的级别
                    level = self.board.getValue((row, col))

                    # 对该棋子四个方向的格子进行遍历
                    for i in range(4):
                        newrow = row + directionList[i][0]
                        newcol = col + directionList[i][1]
                        #如果此方向的格子超界，则不用考虑此方向
                        if newrow < 0 or newrow > 3 or\
                            newcol < 0 or newcol > 7:
                            pass

                        # 如果此方向的格子中为对方的等级别棋子，则要考虑入侵带来的value
                        elif enemySide == self.board.getBelong((newrow, newcol)) and\
                              self.board.getValue((newrow, newcol)) == level:
                            # 对象方为先后手决定了value的正负
                            '''此处的表达式可更改，但应保证先后手的value正负号相反'''
                            invadevalue += (isFirst - 0.5) * level
                            # 对'new'棋子的四个方向进行遍历，若存在对方的高一级别的棋子'newnew'，则value要减小（即吕同学提出的情况）
                            for j in range(4):
                               newnewrow = newrow + directionList[j][0]
                               newnewcol = newcol + directionList[j][1]
                               if newnewrow < 0 or newnewrow > 3 or \
                                    newnewcol < 0 or newnewcol > 7:
                                  pass
                               elif enemySide == self.board.getBelong((newnewrow, newnewcol)) and\
                                    self.board.getValue((newnewrow, newnewcol)) == level + 1:
                                  '''此处表达式可更改，但应保证value要减小，且减小量要比 对象方为先手时的value增量 大'''
                                  invadevalue -= level

                        # 如果此方向为对方空格，则对方可能会隔空击杀，此时value会减小
                        elif enemySide == self.board.getBelong((newrow, newcol)) and\
                              self.board.getValue((newrow, newcol)) == 0:
                            stop = False
                            # 沿该方向前进，若出界，则停下；若碰到对方空格，则继续前进；若碰到对方等级别棋子，则停下并且value减小；其他情况下均停下
                            while not stop:
                              newrow = newrow + directionList[i][0]
                              newcol = newcol + directionList[i][1]
                              # 出界
                              if newrow < 0 or newrow > 3 or \
                                    newcol < 0 or newcol > 7:
                                  stop = True
                              # 碰到对方等级别棋子
                              elif enemySide == self.board.getBelong((newrow, newcol)) and\
                                self.board.getValue((newrow, newcol)) == level:
                                  '''此处的表达式可修改，但应保证value减小'''
                                  invadevalue -= 0.5 * level
                                  stop = True
                              # 碰到对方空格，前进四
                              elif enemySide == self.board.getBelong((newrow, newcol)) and\
                                self.board.getValue((newrow, newcol)) == 0:
                                  stop = False
                              #其他情况，停下
                              else:
                                  stop = True
        return invadevalue
    # 单调性value评估，仅考虑对象方棋盘内的棋子，且对方棋子入侵时，其所在的行与列的value贡献均为0
    def monotonicityValue(self, isFirst):
        import math
        selfSide = isFirst
        monotonicityvalue = 0
        # 遍历每一行
        for row in range(4):
            # 引入单调性因子，表征单行或者单列的单调性好坏
            monotonicityFactor = 0
            # 列数从对象方棋盘的最左列到最右列
            col = (1 - isFirst) * 4
            while col < (1 - isFirst) * 4 + 3:
                # 当前格子的级别
                currentValue = self.board.getValue((row, col))
                # 下一格的坐标
                nextrow = row
                nextcol = col + 1
                # 有内鬼，则终止交易，转至下一行
                if selfSide != self.board.getBelong((row,col)) or\
                        selfSide != self.board.getBelong((nextrow, nextcol)):
                    monotonicityFactor = 0
                    break  # 只是跳出while循环
                # 无内鬼，计算下一格的级别，单调性因子变化
                else:
                    nextValue = self.board.getValue((nextrow, nextcol))
                    '''此表达式可以更改'''
                    monotonicityFactor += nextValue - currentValue
                # 列数加一，继续下一格
                col += 1
            # 此行的单调性因子计算完毕，加至value中
            '''此表达式可以更改'''
            monotonicityvalue += abs(monotonicityFactor)
        # 遍历对象方棋盘每一列
        for col in range((1 - isFirst) * 4, (1 - isFirst) * 4 + 4):
            monotonicityFactor = 0
            row = 0
            while row < 3:
                currentValue = self.board.getValue((row, col))
                nextrow = row + 1
                nextcol = col
                if selfSide != self.board.getBelong((row, col)) or\
                        selfSide != self.board.getBelong((nextrow, nextcol)):
                    monotonicityFactor = 0
                    break
                else:
                    nextValue = self.board.getValue((nextrow, nextcol))
                    monotonicityFactor += nextValue - currentValue
                row += 1
            monotonicityvalue += abs(monotonicityFactor)
        return monotonicityvalue


    '''def checkSidescore(self,isFirst):
        selfscore = self.board.getScore(isFirst)
        enemyscore = self.board.getScore(not isFirst)
        selfscore.reverse()
        enemyscore.reverse()'''


